✨ [FFL-2857] Feature Flags tab — team filtering + token revocation (stacked PR 4 of 4) - #4932
Conversation
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: 1602ea3 | Docs | Datadog PR Page | Give us feedback! |
c88291e to
2a98437
Compare
4c49f6e to
16b1216
Compare
Bundles Sizes Evolution
|
2a98437 to
da1a176
Compare
e4698ab to
c960f4a
Compare
BeltranBulbarellaDD
left a comment
There was a problem hiding this comment.
Overall looks good! Left some comments.
c960f4a to
439df75
Compare
Filter the flag catalog by owning team (teams_read scope + flag identity), and revoke the OAuth grant at Datadog on disconnect rather than only clearing local tokens. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
439df75 to
850a642
Compare
BeltranBulbarellaDD
left a comment
There was a problem hiding this comment.
Overall LGTM! Just some minor edge cases and I think it could be good to merge!
What is the expected behaviour when we are not logged in but we have a local overriden FF? Should it still apply? Cause we have it locally? Because I went to the FF test page and it was in dark mode even though I was unauthenticated.
| <Text>Feature Flags</Text> | ||
| </Tabs.Tab> | ||
| )} | ||
| <Tabs.Tab value={PanelTabs.Flags}> |
There was a problem hiding this comment.
Hm, was thinking about this but i think it might not be worth the cost? it would need the override state at Panel level, so the extension would read the inspected page on every navigation for every user, including everyone who never opens Flags. That might be a lot of extension-wide overhead? i'm also going to add an alert on the Auth login page so that if there are overrides that exist, it will let you know. maybe that can help as well. having the override remain across disconnect and session restarts is intended, but wanted to add some sort of warning to users
- show an override notice on the connect screen so overrides left on the page are visible before authenticating - report success/failure inline on the manual override form, and note that re-applying an existing key replaces its value - stop uppercasing the site badge (datad0g vs datadoghq differ by one glyph) and move Disconnect to the far end of the row - condense inline comments into function-level docs Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The connect screen is dd-privacy-allow, so anything rendered there is unmasked in the extension's own Session Replay. Only a count renders today, but flag keys are customer data — mask the alert so adding them later can't leak silently. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Cut comments that restated the code they sat on, condensed multi-line explanations to their load-bearing sentence, and moved component-level prose into JSDoc. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Success was derived from the stored value alone, so submitting a NUMERIC 1 over a stored INTEGER 1 matched immediately. If the write then failed, the form showed success and hid the error for a change that never landed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BeltranBulbarellaDD
left a comment
There was a problem hiding this comment.
Minor nits but LGTM!
| teamHandles: string[] | ||
| /** True when the team lookup was refused because the user lacks permission to read teams. */ | ||
| teamsForbidden: boolean | ||
| /** True when the team lookup failed for another reason (network/server), distinct from an empty membership. */ |
There was a problem hiding this comment.
I feel the comments do not add any value here.
| borderBottom: '1px solid var(--mantine-color-gray-1)', | ||
| backgroundColor: overridden ? 'var(--mantine-color-violet-0)' : undefined, | ||
| borderBottom: '1px solid var(--mantine-color-default-border)', | ||
| // Mantine's scheme-aware subtle tint (the one variant="light" uses), not a saturated fill. |
There was a problem hiding this comment.
no need I believe
| }, [description, expanded]) | ||
|
|
||
| return ( | ||
| // Slightly more separation than the name↔key gap, so the row reads as "title/key" then "description". |
There was a problem hiding this comment.
i don't think it adds value
| export interface CatalogFlag { | ||
| key: string | ||
| name: string | ||
| /** Free-text description authored in the Datadog UI. Empty when the flag has none. */ |
There was a problem hiding this comment.
The comment is redundant i think?
| tagFilter: string[] | ||
| /** Team handles for the "My teams" filter, sent as `tags=team:<handle>`. */ | ||
| teamFilter: string[] | ||
| /** The signed-in user's UUID when "My feature flags" is on, else null. Sent as `created_by`. */ |
There was a problem hiding this comment.
This comment is repeated above twice.
|
|
||
| /** | ||
| * Revokes the refresh token — the renewable part of the grant. The access token is left to expire | ||
| * (RFC 7009 only *recommends* cascading revocation, so we don't rely on it) and is dropped locally |
There was a problem hiding this comment.
I don't get this line. Should we have a link to the RFC? or remove it?
| const CATALOG_PAGE_SIZE = 20 | ||
| // Wait out a typing burst before sending a search to the server, so we don't fire a request per | ||
| // keystroke. Short enough to still feel responsive. | ||
| // Long enough to wait out a typing burst, short enough to still feel responsive. |
There was a problem hiding this comment.
No need, we know what a debounce is.
Remove field docs that repeated their own names or the enclosing interface doc, and replace the opaque RFC 7009 aside on tryRevokeGrant with a plain explanation plus a link on revokeAndClearTokens. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Motivation
Stacked on #4912 (flag overrides). Adds team/creator filtering + per-flag descriptions to the Feature Flags tab, plus production OAuth support and token revocation on disconnect.
Stack (review bottom-up)
mainffl-2597mainffl-2596Changes
created_by=<uuid>; "My teams" →tags=team:<handle>. Identity (user UUID + team handles) comes from/api/v2/current_user+/api/v2/team?filter[me]=true. "My teams" is a checkbox dropdown showing an "N selected" summary.descriptionattribute), with a "Show more" expander that only appears when the text is actually clamped.getClientId— staging vs prod); site picker trimmed to US1 + Staging./oauth2/v1/revoke— revokes the refresh token, clears local tokens either way).teams_read(viainvalid_scoperedirect or an authorize page-load failure).DEMO
Note, we can now choose between datadoghq.com and staging. There are also filters for My Feature Flags and My Teams. Descriptions are fetched as well.
Screen.Recording.2026-08-10.at.1.26.56.PM.mov
Checklist